package com.lyf.scm.plan.domain.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.*;
import com.lyf.scm.common.model.ExcelExportDataDTO;
import com.lyf.scm.common.util.AdvancedSearchUtil;
import com.lyf.scm.common.util.ExcelExportUtil;
import com.lyf.scm.common.util.date.MyDateUtil;
import com.lyf.scm.common.util.style.GeneralCellWriteHandler;
import com.lyf.scm.plan.api.dto.RoleAuthorityAreaDTO;
import com.lyf.scm.plan.api.dto.SalesPlanOtherAccuracyDTO;
import com.lyf.scm.plan.api.dto.SalesPlanOtherAccuracyInfoDTO;
import com.lyf.scm.plan.domain.convertor.SalesPlanOtherAccuracyConvertor;
import com.lyf.scm.plan.domain.remote.item.dto.SkuUnitDTO;
import com.lyf.scm.plan.domain.remote.item.facade.ItemCoreFacade;
import com.lyf.scm.plan.domain.repository.RoleAuthorityAreaRepository;
import com.lyf.scm.plan.domain.repository.SalesPlanOtherAccuracyRespository;
import com.lyf.scm.plan.domain.repository.SalesPlanOtherRespository;
import com.lyf.scm.plan.domain.service.SalesPlanOtherAccuracyService;
import com.lyf.scm.plan.insfrastructure.db.dataobject.SalesPlanOtherAccuracyDO;
import com.rome.arch.core.exception.RomeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * description:
 * 其他渠道计划_目标与销售计划准确率serviceImpl
 *
 * @author: huangtao
 * @data: 2020/7/31
 */
@Slf4j
@Service
public class SalesPlanOtherAccuracyServiceImpl implements SalesPlanOtherAccuracyService {
    @Resource
    private SalesPlanOtherAccuracyRespository salesPlanOtherAccuracyRespository;
    
    @Resource
    private ItemCoreFacade itemCoreFacade;

    @Resource
    private SalesPlanOtherAccuracyConvertor salesPlanOtherAccuracyConvertor;

    @Resource
    private SalesPlanOtherRespository salesPlanOtherRespository;

    @Resource
    private RoleAuthorityAreaRepository roleAuthorityAreaRepository;

    /**
     * 按条件查询其他渠道计划_目标与销售计划准确率（周）
     *
     * @param salesPlanOtherAccuracy
     * @return
     */
    @Override
    public PageInfo<SalesPlanOtherAccuracyInfoDTO> listWeekBySelective(SalesPlanOtherAccuracyDTO salesPlanOtherAccuracy) {
        //根据日期获取间隔日期集合,没有结束时间，默认14周
        List<Map<String, Date>> weekDates = MyDateUtil.getWeekDates(salesPlanOtherAccuracy.getStartTime(), CommonConstants.WEEK_SIZE);
        salesPlanOtherAccuracy.setWeekDateList(weekDates);
        salesPlanOtherAccuracy.setEndTime(MyDateUtil.getLastDate(null, weekDates));
        PageInfo<SalesPlanOtherAccuracyInfoDTO> dtoPageInfo = new PageInfo<>();
        Long userId = salesPlanOtherAccuracy.getCreator();
        //获取当前用户角色权限
        List<RoleAuthorityAreaDTO> roleAreaList = roleAuthorityAreaRepository.listByUserId(userId);
        if (CollectionUtils.isEmpty(roleAreaList)) {
            throw new RomeException(ResponseMsg.FAIL_2004.getCode(), ResponseMsg.FAIL_2004.getMsg());
        }
        //渠道不为空为其他渠道计划用户
        roleAreaList = roleAreaList.stream().filter(item -> ObjectUtil.isNotNull(item.getChannelCode())).collect(Collectors.toList());
        List<String> channels = new ArrayList<>();
        roleAreaList.forEach(item -> {
            String channel = item.getChannelCode();
            channels.add(channel);
        });
        //高级搜索不选择渠道，查询用户对应渠道
        if (CollectionUtils.isEmpty(salesPlanOtherAccuracy.getChannelCodeList())) {
            salesPlanOtherAccuracy.setChannelCodeList(channels);
        }
        //根据高级搜索条件查询分页的信息
        PageInfo<SalesPlanOtherAccuracyDO> listPageInfo = salesPlanOtherRespository.listWeekBySelectiveAccuracy(salesPlanOtherAccuracy);
        List<SalesPlanOtherAccuracyDO> list = listPageInfo.getList();
        SalesPlanOtherAccuracyDO salesPlanOtherAccuracyDO = dealData(list, salesPlanOtherAccuracy);
        //查询对应的指标
        if (ObjectUtil.isNotEmpty(list)) {
            List<SalesPlanOtherAccuracyDTO> salesPlan = salesPlanOtherRespository.listSalesAndTargetAccuracy(salesPlanOtherAccuracyDO);
            if (!SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(salesPlanOtherAccuracy.getUnitType())) {
                //获取不重复的skuCode集合
                List<String> skuCodeList = salesPlan.stream().map(SalesPlanOtherAccuracyDTO::getSkuCode).distinct().collect(Collectors.toList());
                //处理单位
                List<SkuUnitDTO> skuUnitList = itemCoreFacade.getConversionRatio(skuCodeList, salesPlanOtherAccuracy.getUnitType());
                this.calculationPro(salesPlan, skuUnitList);
            }
            //设置分组依据的key值
            this.getGroupByKey(salesPlan, salesPlanOtherAccuracy);
            //将数据分组
            Map<String, List<SalesPlanOtherAccuracyDTO>> collect = salesPlan.stream().collect(Collectors.groupingBy(SalesPlanOtherAccuracyDTO::getCondition, Collectors.toList()));
            //处理分组后的数据
            dtoPageInfo.setList(this.getTargetList(collect, salesPlanOtherAccuracy));
            dtoPageInfo.setTotal(collect.values().size());
        }
        return dtoPageInfo;
    }

    /**
     * 查询全渠道其他渠道计划_目标与销售计划准确率(范围)
     * @param salesPlanOtherAccuracy
     * @return
     */
    @Override
    public List<SalesPlanOtherAccuracyInfoDTO> listAllByCycles(SalesPlanOtherAccuracyDTO salesPlanOtherAccuracy) {
        //如果开始时间为空
        if (ObjectUtil.isEmpty(salesPlanOtherAccuracy.getStartTime())) {
            salesPlanOtherAccuracy.setStartTime(DateUtil.beginOfWeek(new Date()));
        } else {
            salesPlanOtherAccuracy.setStartTime(DateUtil.beginOfWeek(salesPlanOtherAccuracy.getStartTime()));
        }
        //如果结束时间为空
        if (ObjectUtil.isEmpty(salesPlanOtherAccuracy.getEndTime())) {
            salesPlanOtherAccuracy.setEndTime(DateUtil.beginOfWeek(DateUtil.offsetWeek(new Date(), CommonConstants.WEEK_TARGET_SIZE)));
        } else {
            salesPlanOtherAccuracy.setEndTime(DateUtil.endOfWeek(salesPlanOtherAccuracy.getEndTime()));
        }
        Long userId = salesPlanOtherAccuracy.getCreator();
        //获取当前用户角色权限
        List<RoleAuthorityAreaDTO> roleAreaList = roleAuthorityAreaRepository.listByUserId(userId);
        if (CollectionUtils.isEmpty(roleAreaList)) {
            throw new RomeException(ResponseMsg.FAIL_2004.getCode(), ResponseMsg.FAIL_2004.getMsg());
        }
        //渠道不为空为其他渠道计划用户
        roleAreaList = roleAreaList.stream().filter(item -> ObjectUtil.isNotNull(item.getChannelCode())).collect(Collectors.toList());
        List<String> channels = new ArrayList<>();
        roleAreaList.forEach(item -> {
            String channel = item.getChannelCode();
            channels.add(channel);
        });
        salesPlanOtherAccuracy.setChannelCodeList(channels);
        List<SalesPlanOtherAccuracyDTO> resultList = salesPlanOtherRespository.listAllByCyclesAccuracy(salesPlanOtherAccuracy);
        if (!SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(salesPlanOtherAccuracy.getUnitType())) {
            //获取不重复的skuCode集合
            List<String> skuCodeList = resultList.stream().map(SalesPlanOtherAccuracyDTO::getSkuCode).distinct().collect(Collectors.toList());
            //获取单位换算比例
            List<SkuUnitDTO> skuUnitList = itemCoreFacade.getConversionRatio(skuCodeList, salesPlanOtherAccuracy.getUnitType());
            //根据获取的换算比例计算指标数量
            this.calculationPro(resultList, skuUnitList);
        }

        //设置分组依据的key值
        this.getGroupByKey(resultList, salesPlanOtherAccuracy);
        //查询柱状图不分组
        resultList.forEach(item -> {
            item.setCondition("");
        });
        //将数据分组
        Map<String, List<SalesPlanOtherAccuracyDTO>> paramMap = resultList.stream().collect(Collectors.groupingBy(SalesPlanOtherAccuracyDTO::getCondition, Collectors.toList()));
        // 汇总分组后的数据
        List<SalesPlanOtherAccuracyInfoDTO> salesPlanDirectlyList = this.getTargetList(paramMap, salesPlanOtherAccuracy);
        return salesPlanDirectlyList;
    }

    /**
     * 导出所有查询数据
     *
     * @param salesPlanOtherAccuracyDTO
     * @param type
     * @throws Exception
     */
    @Override
    public ExcelExportDataDTO export(SalesPlanOtherAccuracyDTO salesPlanOtherAccuracyDTO, Integer type) throws Exception {
        //指标名称集合
        List<String> allTargetsDesc = SalesPlanOtherAccuracyEnum.getAllTargetsDesc();
        //获取日期标题
        List<String> dateTitles = MyDateUtil.processCyclesDate(salesPlanOtherAccuracyDTO.getWeekDateList(), "MM.dd");
        //增加合计
        dateTitles.add("合计");
        List<SalesPlanOtherAccuracyDTO> salesPlanDTOList = new ArrayList<>();
        List<List<Object>> exportDataList = null;
        Long userId = salesPlanOtherAccuracyDTO.getCreator();
        //获取当前用户角色权限
        List<RoleAuthorityAreaDTO> roleAreaList = roleAuthorityAreaRepository.listByUserId(userId);
        if (CollectionUtils.isEmpty(roleAreaList)) {
            throw new RomeException(ResponseMsg.FAIL_2004.getCode(), ResponseMsg.FAIL_2004.getMsg());
        }
        //渠道不为空为其他渠道计划用户
        roleAreaList = roleAreaList.stream().filter(item -> ObjectUtil.isNotNull(item.getChannelCode())).collect(Collectors.toList());
        List<String> channels = new ArrayList<>();
        roleAreaList.forEach(item -> {
            String channel = item.getChannelCode();
            channels.add(channel);
        });
        //高级搜索不选择渠道，查询用户对应渠道
        if (CollectionUtils.isEmpty(salesPlanOtherAccuracyDTO.getChannelCodeList())) {
            salesPlanOtherAccuracyDTO.setChannelCodeList(channels);
        }
        //全部数据导出
        if (ExcelExportTypeEnum.SEARCHED_DATA_EXPORT.getType().equals(type)) {
            salesPlanDTOList = salesPlanOtherRespository.listAllByConditionAccuracy(salesPlanOtherAccuracyDTO);
        }
        //当前页数据导出
        if (ExcelExportTypeEnum.CURRENT_PAGE_EXPORT.getType().equals(type)) {
            List<SalesPlanOtherAccuracyDO> list = salesPlanOtherRespository.listWeekBySelectiveAccuracy(salesPlanOtherAccuracyDTO).getList();
            if (ObjectUtil.isNotEmpty(list)) {
                SalesPlanOtherAccuracyDO salesPlanOtherAccuracyDO = dealData(list, salesPlanOtherAccuracyDTO);
                salesPlanDTOList = salesPlanOtherRespository.listSalesAndTargetAccuracy(salesPlanOtherAccuracyDO);
            }
        }
        //导出选中的数据
        if (ExcelExportTypeEnum.CHECKED_BOX_EXPORT.getType().equals(type)) {
            SalesPlanOtherAccuracyDO salesPlanOtherAccuracyDO = dealData(salesPlanOtherAccuracyConvertor.dtoToDO(salesPlanOtherAccuracyDTO.getSalesPlanOtherAccuracyList()), salesPlanOtherAccuracyDTO);
            salesPlanDTOList = salesPlanOtherRespository.listSalesAndTargetAccuracy(salesPlanOtherAccuracyDO);
        }
        if (CollectionUtils.isEmpty(salesPlanDTOList)) {
            throw new RomeException(ResponseMsg.FAIL_2005.getCode(), ResponseMsg.FAIL_2005.getMsg());
        }
        if (!SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(salesPlanOtherAccuracyDTO.getUnitType())) {
            //获取不重复的skuCode集合
            List<String> skuCodeList = salesPlanDTOList.stream().map(SalesPlanOtherAccuracyDTO::getSkuCode).distinct().collect(Collectors.toList());
            //处理单位
            List<SkuUnitDTO> skuUnitList = itemCoreFacade.getConversionRatio(skuCodeList, salesPlanOtherAccuracyDTO.getUnitType());
            this.calculationPro(salesPlanDTOList, skuUnitList);
        }

        //设置分组依据的key值
        this.getGroupByKey(salesPlanDTOList, salesPlanOtherAccuracyDTO);
        //将数据分组
        Map<String, List<SalesPlanOtherAccuracyDTO>> paramMap = salesPlanDTOList.stream().collect(Collectors.groupingBy(SalesPlanOtherAccuracyDTO::getCondition, Collectors.toList()));
        //全部数据导出
        exportDataList = this.getExcelTargetList(paramMap, salesPlanOtherAccuracyDTO, allTargetsDesc, dateTitles);
        //获取所有查询条件标识
        List<String> conditions = this.getConditions(salesPlanOtherAccuracyDTO);
        //获取excel标题 同时返回高级搜索标题的数量
        List<List<String>> heads = new ArrayList<>();
        int mergeCellsColumns = this.setExcelTitles(heads, conditions, dateTitles);
        return ExcelExportUtil.getExcelExportData(mergeCellsColumns, exportDataList, heads, allTargetsDesc.size(), new GeneralCellWriteHandler());

    }
    
    /**
     * 根据获取的换算比例计算指标数量
     */
    private List<SalesPlanOtherAccuracyDTO> calculationPro(List<SalesPlanOtherAccuracyDTO> resultList, List<SkuUnitDTO> skuUnitList) {
        if (CollectionUtils.isNotEmpty(skuUnitList) && CollectionUtils.isNotEmpty(resultList)) {
            skuUnitList.forEach(skuUnit -> {
                resultList.forEach(item -> {
                    if (item.getSkuCode().equals(skuUnit.getSkuCode())) {
                        item.setPlanQty(ObjectUtil.isNotEmpty(item.getPlanQty()) ?  item.getPlanQty().divide(BigDecimal.valueOf(skuUnit.getScale()), 7, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
                        item.setActualConfirmedQty(ObjectUtil.isNotEmpty(item.getActualConfirmedQty()) ?  item.getActualConfirmedQty().divide(BigDecimal.valueOf(skuUnit.getScale()), 7, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
                        item.setActualSalesQty(ObjectUtil.isNotEmpty(item.getActualSalesQty()) ?  item.getActualSalesQty().divide(BigDecimal.valueOf(skuUnit.getScale()), 7, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
                    }
                });
            });
        }
        return resultList;
    }

    /**
     * 设置分组依据的key值
     *
     * @param salesPlanOtherPlans 其他渠道计划dos
     * @return {@link List<SalesPlanOtherAccuracyDTO>}
     */
    private List<SalesPlanOtherAccuracyDTO> getGroupByKey(List<SalesPlanOtherAccuracyDTO> salesPlanOtherPlans,SalesPlanOtherAccuracyDTO salesPlanOtherAccuracyDTO) {
        salesPlanOtherPlans.forEach(item -> {
            StringBuilder keyStr = new StringBuilder();
            keyStr.append(ObjectUtil.isNotNull(item.getChannelCode()) ? item.getChannelCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getSubChannelCode()) ? item.getSubChannelCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getPriCategoryCode()) ? item.getPriCategoryCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getSecCategoryCode()) ? item.getSecCategoryCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getTerCategoryCode()) ? item.getTerCategoryCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getProvinceCode()) ? item.getProvinceCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getCityCode()) ? item.getCityCode() : "");
            keyStr.append(ObjectUtil.isNotNull(item.getCountyCode()) ? item.getCountyCode() : "");
            if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getSkuCodeList())) {
                keyStr.append(ObjectUtil.isNotNull(item.getSkuCode()) ? item.getSkuCode() : "");
            }
            if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getStoreCodeList())) {
                keyStr.append(ObjectUtil.isNotNull(item.getStoreCode()) ? item.getStoreCode() : "");
            }
            item.setCondition(keyStr.toString());
        });
        return salesPlanOtherPlans;
    }

    /**
     * 汇总分组后的数据
     *
     * @param paramMap       参数映射
     * @param salesPlanOtherAccuracy 其他渠道计划
     * @return {@link List<SalesPlanOtherAccuracyInfoDTO>}
     */
    private List<SalesPlanOtherAccuracyInfoDTO> getTargetList(Map<String, List<SalesPlanOtherAccuracyDTO>> paramMap, SalesPlanOtherAccuracyDTO salesPlanOtherAccuracy) {
        List<SalesPlanOtherAccuracyInfoDTO> SalesPlanOtherAccuracyInfoList = new ArrayList<>();
        List<Map<String, Date>> weekDateList = salesPlanOtherAccuracy.getWeekDateList();
        //将分组后的数据汇总
        paramMap.keySet().forEach(key -> {
            List<BigDecimal> planQtys= new ArrayList<>();
            List<BigDecimal> actualConfirmedQtys= new ArrayList<>();
            List<BigDecimal> actualSalesQtys= new ArrayList<>();
            List<BigDecimal> planAccuracys= new ArrayList<>();
            SalesPlanOtherAccuracyInfoDTO salesPlanOtherAccuracyInfo = new SalesPlanOtherAccuracyInfoDTO();
            // 设置计划值
            weekDateList.forEach(date -> planQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getPlanQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setPlanQtyLabel(SalesPlanOtherAccuracyEnum.PLAN_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setPlanQtys(planQtys);
            // 设置实际确认量
            weekDateList.forEach(date -> actualConfirmedQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getActualConfirmedQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setActualConfirmedQtyLabel(SalesPlanOtherAccuracyEnum.ACTUAL_CONFIRMED_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setActualConfirmedQtys(actualConfirmedQtys);
            // 设置实际销量（没有接口，先展示实际确认量）
            weekDateList.forEach(date -> actualSalesQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getActualConfirmedQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setActualSalesQtyLabel(SalesPlanOtherAccuracyEnum.ACTUAL_SALES_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setActualSalesQtys(actualSalesQtys);
            // 计划准确率:（销售计划量-真实销量）/真实销量
            for (int i = 0; i < weekDateList.size(); i++) {
                planAccuracys.add(actualSalesQtys.get(i).compareTo(BigDecimal.ZERO) == 0 || planQtys.get(i).subtract(actualSalesQtys.get(i)).compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : (planQtys.get(i).subtract(actualSalesQtys.get(i))).divide(actualSalesQtys.get(i), 7, BigDecimal.ROUND_HALF_UP));
            }
            salesPlanOtherAccuracyInfo.setPlanAccuracyLabel(SalesPlanOtherAccuracyEnum.PLAN_ACCURACY.getDesc());
            salesPlanOtherAccuracyInfo.setPlanAccuracys(planAccuracys);
            //获取渠道、区域、商品信息
            this.getInfoData(paramMap.get(key), salesPlanOtherAccuracyInfo, salesPlanOtherAccuracy.getSkuCodeList());
            SalesPlanOtherAccuracyInfoList.add(salesPlanOtherAccuracyInfo);
        });
        return SalesPlanOtherAccuracyInfoList;
    }

    /**
     * 获取渠道、区域、商品信息
     *
     * @param salesPlanOthers
     * @param salesPlanOtherAccuracyInfo
     * @param skuCodeList
     * @return
     */
    private SalesPlanOtherAccuracyInfoDTO getInfoData(List<SalesPlanOtherAccuracyDTO> salesPlanOthers, SalesPlanOtherAccuracyInfoDTO salesPlanOtherAccuracyInfo, List<String> skuCodeList) {
        /**
         * 区域信息
         */
        salesPlanOtherAccuracyInfo.setArea(
                salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getProvinceName())).map(SalesPlanOtherAccuracyDTO::getProvinceName).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getCityName())).map(e -> "/" + e.getCityName()).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getCountyName())).map(e -> "/" + e.getCountyName()).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getStoreName())).map(e -> "/" + e.getStoreName()).distinct().collect(Collectors.joining()));
        // 渠道信息
        salesPlanOtherAccuracyInfo.setChannel(
                salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getChannelName())).map(SalesPlanOtherAccuracyDTO::getChannelName).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getSubChannelName())).map(e -> "/" + e.getSubChannelName()).distinct().collect(Collectors.joining()));
        // 品类信息
        salesPlanOtherAccuracyInfo.setCategory(
                salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getPriCategoryName())).map(SalesPlanOtherAccuracyDTO::getPriCategoryName).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getSecCategoryName())).map(e -> "/" + e.getSecCategoryName()).distinct().collect(Collectors.joining()) +
                        salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getTerCategoryName())).map(e -> "/" + e.getTerCategoryName()).distinct().collect(Collectors.joining()));
        //sku信息
        if (CollectionUtils.isNotEmpty(skuCodeList)) {
            salesPlanOtherAccuracyInfo.setSkuCode(salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getSkuCode())).map(SalesPlanOtherAccuracyDTO::getSkuCode).distinct().collect(Collectors.joining()));
            salesPlanOtherAccuracyInfo.setSkuName(salesPlanOthers.stream().filter(item -> ObjectUtil.isNotNull(item.getSkuName())).map(SalesPlanOtherAccuracyDTO::getSkuName).distinct().collect(Collectors.joining()));
        }
        //一级渠道
        salesPlanOtherAccuracyInfo.setChannelCode(salesPlanOthers.get(0).getChannelCode());
        salesPlanOtherAccuracyInfo.setSubChannelCode(salesPlanOthers.get(0).getSubChannelCode());
        salesPlanOtherAccuracyInfo.setPriCategoryCode(salesPlanOthers.get(0).getPriCategoryCode());
        salesPlanOtherAccuracyInfo.setSecCategoryCode(salesPlanOthers.get(0).getSecCategoryCode());
        salesPlanOtherAccuracyInfo.setTerCategoryCode(salesPlanOthers.get(0).getSecCategoryCode());
        salesPlanOtherAccuracyInfo.setStoreCode(salesPlanOthers.get(0).getStoreCode());
        salesPlanOtherAccuracyInfo.setProvinceCode(salesPlanOthers.get(0).getProvinceCode());
        salesPlanOtherAccuracyInfo.setCityCode(salesPlanOthers.get(0).getCityCode());
        salesPlanOtherAccuracyInfo.setCountyCode(salesPlanOthers.get(0).getCountyCode());
        return salesPlanOtherAccuracyInfo;
    }


    /**
     * 处理查询出来的条数和数据
     */
    private SalesPlanOtherAccuracyDO dealData(List<SalesPlanOtherAccuracyDO> list, SalesPlanOtherAccuracyDTO salesPlanOtherAccuracy) {
        //处理查询出来的数据
        //把查询的结果代入新的对象中，用于查询数据
        SalesPlanOtherAccuracyDO salesPlanDO = new SalesPlanOtherAccuracyDO();
        if (ObjectUtil.isNotEmpty(list)) {
            salesPlanDO.setChannelCode(list.get(0).getChannelCode());
            salesPlanDO.setSubChannelCode(list.get(0).getSubChannelCode());
            salesPlanDO.setProvinceCode(list.get(0).getProvinceCode());
            salesPlanDO.setCityCode(list.get(0).getCityCode());
            salesPlanDO.setCountyCode(list.get(0).getCountyCode());
            salesPlanDO.setPriCategoryCode(list.get(0).getPriCategoryCode());
            salesPlanDO.setSecCategoryCode(list.get(0).getSecCategoryCode());
            salesPlanDO.setTerCategoryCode(list.get(0).getTerCategoryCode());
            salesPlanDO.setSkuCode(list.get(0).getSkuCode());
            salesPlanDO.setType(list.get(0).getType());
            salesPlanDO.setSalesPlanOtherAccuracyList(list);
        }
        salesPlanDO.setStartTime(salesPlanOtherAccuracy.getStartTime());
        salesPlanDO.setEndTime(salesPlanOtherAccuracy.getEndTime());
        return salesPlanDO;
    }

    /**
     * Excel中的每条数据
     *
     * @param paramMap
     * @param salesPlanOtherAccuracy
     * @param targets
     * @param dateTitles
     * @return
     */
    private List<List<Object>> getExcelTargetList(Map<String, List<SalesPlanOtherAccuracyDTO>> paramMap, SalesPlanOtherAccuracyDTO salesPlanOtherAccuracy, List<String> targets, List<String> dateTitles) {
        List<SalesPlanOtherAccuracyInfoDTO> SalesPlanOtherAccuracyInfoList = new ArrayList<>();
        List<Map<String, Date>> weekDateList = salesPlanOtherAccuracy.getWeekDateList();
        List<List<Object>> exportDataList = new ArrayList<>();
        //将分组后的数据汇总
        paramMap.keySet().forEach(key -> {
            List<BigDecimal> planQtys= new ArrayList<>();
            List<BigDecimal> actualConfirmedQtys= new ArrayList<>();
            List<BigDecimal> actualSalesQtys= new ArrayList<>();
            List<BigDecimal> planAccuracys= new ArrayList<>();
            SalesPlanOtherAccuracyInfoDTO salesPlanOtherAccuracyInfo = new SalesPlanOtherAccuracyInfoDTO();
            // 设置计划值
            weekDateList.forEach(date -> planQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getPlanQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setPlanQtyLabel(SalesPlanOtherAccuracyEnum.PLAN_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setPlanQtys(planQtys);
            // 设置实际确认量
            weekDateList.forEach(date -> actualConfirmedQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getActualConfirmedQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setActualConfirmedQtyLabel(SalesPlanOtherAccuracyEnum.ACTUAL_CONFIRMED_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setActualConfirmedQtys(actualConfirmedQtys);
            // 设置实际销量(没有接口，先展示实际确认量)
            weekDateList.forEach(date -> actualSalesQtys.add(paramMap.get(key).stream().filter(item -> item.getPlanStartDate().compareTo(date.get("startTime")) == 0 && item.getPlanEndDate().compareTo(date.get("endTime")) == 0).map(SalesPlanOtherAccuracyDTO::getActualConfirmedQty).reduce(BigDecimal.ZERO, BigDecimal::add)));
            salesPlanOtherAccuracyInfo.setActualSalesQtyLabel(SalesPlanOtherAccuracyEnum.ACTUAL_SALES_QTY.getDesc());
            salesPlanOtherAccuracyInfo.setActualSalesQtys(actualSalesQtys);
            // 计划准确率:（销售计划量-真实销量）/真实销量
            for (int i = 0; i < weekDateList.size(); i++) {
                planAccuracys.add(actualSalesQtys.get(i).compareTo(BigDecimal.ZERO) == 0 || planQtys.get(i).subtract(actualSalesQtys.get(i)).compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : (planQtys.get(i).subtract(actualSalesQtys.get(i))).divide(actualSalesQtys.get(i), 7, BigDecimal.ROUND_HALF_UP));
            }
            salesPlanOtherAccuracyInfo.setPlanAccuracyLabel(SalesPlanOtherAccuracyEnum.PLAN_ACCURACY.getDesc());
            salesPlanOtherAccuracyInfo.setPlanAccuracys(planAccuracys);
            //获取渠道、区域、商品信息
            this.getInfoData(paramMap.get(key), salesPlanOtherAccuracyInfo, salesPlanOtherAccuracy.getSkuCodeList());

            for (int i = 0; i < targets.size(); i++) {
                List<Object> itemRow = new ArrayList<>();
                //加入渠道，区域，品类，商品  信息
                this.setExcelRowAdvancedSearchCondition(salesPlanOtherAccuracyInfo, itemRow);
                //加入指标
                itemRow.add(targets.get(i));
                //加入数据
                for (int j = 0; j < (dateTitles.size() - 1); j++) {
                    //获取指标集合，这里没有排序，默认使用枚举的顺序
                    switch (i) {
                        case 0:
                            itemRow.add(planQtys.get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : planQtys.get(j));
                            break;
                        case 1:
                            itemRow.add(actualConfirmedQtys.get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : actualConfirmedQtys.get(j));
                            break;
                        case 2:
                            itemRow.add(actualSalesQtys.get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : actualSalesQtys.get(j));
                            break;
                        case 3:
                            itemRow.add(planAccuracys.get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : (planAccuracys.get(j).multiply(new BigDecimal(100.000)).setScale(3, BigDecimal.ROUND_HALF_UP)) + "%");
                            break;
                        default:
                            break;
                    }
                }
                //合计
                BigDecimal total = BigDecimal.ZERO;
                String percentage = "";
                //获取除日期外的下标
                int index = itemRow.size() - (dateTitles.size() - 1);
                List<Object> numRow = new ArrayList<>();
                numRow.addAll(itemRow);
                for (int a = 0; a < index; a++) {
                    numRow.remove(numRow.get(0));
                }
                //循环增加查询的日期对应指标数量
                for (Object obj : numRow) {
                    BigDecimal num = BigDecimal.ZERO;
                    if ("-".equals(obj)) {
                        num = BigDecimal.ZERO;
                        total = total.add(num);
                    } else {
                        if (obj.toString().contains("%")) {
                            String nums = obj.toString().substring(0, obj.toString().length() - 1);
                            num = new BigDecimal(nums);
                            total = total.add(num);
                            percentage = total + "%";
                        } else {
                            num = new BigDecimal(obj.toString());
                            total = total.add(num);
                        }
                    }
                }
                if ("".equals(percentage)) {
                    itemRow.add(total.equals(BigDecimal.ZERO) ? "-" : total);
                } else {
                    itemRow.add(percentage);
                }

                exportDataList.add(itemRow);
            }
        });
        return exportDataList;
    }

    /**
     * excel每行数据设置 高级搜索  信息
     *
     * @param salesPlanOtherAccuracyInfo
     * @param itemRow
     * @return void
     **/
    private void setExcelRowAdvancedSearchCondition(SalesPlanOtherAccuracyInfoDTO salesPlanOtherAccuracyInfo, List<Object> itemRow) {
        if (!StringUtils.isEmpty(salesPlanOtherAccuracyInfo.getChannel())) {
            itemRow.add(salesPlanOtherAccuracyInfo.getChannel());
        }
        if (!StringUtils.isEmpty(salesPlanOtherAccuracyInfo.getArea())) {
            itemRow.add(salesPlanOtherAccuracyInfo.getArea());
        }
        if (!StringUtils.isEmpty(salesPlanOtherAccuracyInfo.getCategory())) {
            itemRow.add(salesPlanOtherAccuracyInfo.getCategory());
        }
        if (!StringUtils.isEmpty(salesPlanOtherAccuracyInfo.getSkuName())) {
            itemRow.add(salesPlanOtherAccuracyInfo.getSkuName());
        }
    }

    /**
     * 获取分组条件
     *
     * @param salesPlanOtherAccuracyDTO
     * @return
     */
    private List<String> getConditions(SalesPlanOtherAccuracyDTO salesPlanOtherAccuracyDTO) {
        List<String> conditions = new ArrayList<>();
        if (CollectionUtils.isEmpty(salesPlanOtherAccuracyDTO.getChannelCodeList())) {
            conditions.add(BaseSearchColumnEnum.CHANNEL_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getChannelCodeList())) {
            conditions.add(BaseSearchColumnEnum.SUB_CHANNEL_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getProvinceCodeList())) {
            conditions.add(BaseSearchColumnEnum.PROVINCE_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getCityCodeList())) {
            conditions.add(BaseSearchColumnEnum.CITY_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getCountyCodeList())) {
            conditions.add(BaseSearchColumnEnum.COUNTY_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getStoreCodeList())) {
            conditions.add(BaseSearchColumnEnum.STORE_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getPriCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.PRI_CATEGORY_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getSecCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.SEC_CATEGORY_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getTerCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.TER_CATEGORY_CODE.getColumn());
        }
        if (CollectionUtils.isNotEmpty(salesPlanOtherAccuracyDTO.getSkuCodeList())) {
            conditions.add(BaseSearchColumnEnum.SKU_CODE.getColumn());
            conditions.add(BaseSearchColumnEnum.TER_CATEGORY_CODE.getColumn());
        }
        return conditions;
    }
    private int setExcelTitles(List<List<String>> heads, List<String> conditions, List<String> dateTitles) {
        //获取高级搜索标题
        this.getExcelAdvancedSearchTitle(heads, conditions);
        int result = heads.size();
        //加入指标标题
        List<String> targetTitle = new ArrayList<>();
        targetTitle.add(ExcelExportTitleEnum.TARGET_TITLE.getTitle());
        heads.add(targetTitle);
        //加入日期标题
        AdvancedSearchUtil.getExcelDateTitle(heads, dateTitles);
        return result;
    }

    /**
     * Excel表头
     *
     * @param heads
     * @param conditions
     */
    private void getExcelAdvancedSearchTitle(List<List<String>> heads, List<String> conditions) {
        if (conditions.contains(BaseSearchColumnEnum.CHANNEL_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CHANNEL_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.SUB_CHANNEL_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CHANNEL_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.PROVINCE_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.AREA_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.CITY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.AREA_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.COUNTY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.AREA_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.STORE_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.AREA_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.PRI_CATEGORY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CATEGORY_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.SEC_CATEGORY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CATEGORY_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.TER_CATEGORY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CATEGORY_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.SKU_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CATEGORY_TITLE.getTitle());
        }
    }
    /**
     * 获取标题行list
     *
     * @param heads
     * @param title
     */
    private static void setList(List<List<String>> heads, String title) {
        List<String> list = new ArrayList<>();
        list.add(title);
        heads.add(list);
    }
    @Override
    public void delete(String opSign) {
        salesPlanOtherAccuracyRespository.delete(opSign);
    }
}
